﻿using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using AutoMapper;
using Illinois.Core.Interfaces;
using Illinois.Core.Models;
using Illinois.Infrastructure.Models;

namespace Illinois.Infrastructure.Data
{
  // see: http://weblogs.asp.net/scottgu/archive/2011/01/11/vs-2010-sp1-and-sql-ce.aspx
  public class IllinoisContext : DbContext, IBurnDownRepository // todo: is this an UoW rather than a repo? Yes it is!
  {
    public DbSet<BurnDownData> BurnDowns { get; set; }
    public DbSet<StoryPointsData> StoryPoints { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
      modelBuilder.Entity<BurnDownData>().HasMany<StoryPointsData>(e => e.StoryPointsWrapList);
    }

    public int Save(IBurnDown burnDown)
    {
      // mapping
      Mapper.CreateMap<IBurnDown, BurnDownData>();
      var entity = Mapper.Map<IBurnDown, BurnDownData>(burnDown);
      // /mapping
      BurnDowns.Add(entity);
      return SaveChanges();
    }

    public int Delete(int burnDownId)
    {
      var points = StoryPoints.Where(e => e.BurnDownData.Id == burnDownId);
      foreach (var point in points)
      {
        StoryPoints.Remove(point);
      }
      var entity = BurnDowns.Find(burnDownId);
      BurnDowns.Remove(entity);
      return SaveChanges();
    }

    public IBurnDown GetById(int burnDownId)
    {
      var item = BurnDowns.Find(burnDownId);
      if (item != null)
        item.StoryPointsWrapList = StoryPoints.Where(e => e.BurnDownData.Id == burnDownId).OrderBy(e => e.Order).ToList();
      return item;
    }

    public IList<IBurnDown> GetAll(int projectId)
    {
      return BurnDowns.Where(e => e.ProjectId == projectId).ToList().OrderByDescending(e => e.Id).Cast<IBurnDown>().ToList();
    }

    public int SaveStoryPoints(int burnDownId, IStoryPoints storyPoints)
    {
      // todo: refactor this
      if (storyPoints.Id == -1)
      {
        // add
        var entity = BurnDowns.Find(burnDownId);
        entity.StoryPointsWrapList.Add(new StoryPointsData { Order = storyPoints.Order, Value = storyPoints.Value });
      }
      else
      {
        if (storyPoints.Value == -1)
        {
          // delete
          var entity = StoryPoints.Find(storyPoints.Id);
          StoryPoints.Remove(entity);
        }
        else
        {
          // update
          var entity = StoryPoints.Find(storyPoints.Id);
          entity.Value = storyPoints.Value;
        }
      }
      return SaveChanges();
    }

    public int UpdateMetaData(int burnDownId, string title, int points)
    {
      // get entity by id
      var entity = BurnDowns.Include("StoryPointsWrapList").First(e => e.Id ==  burnDownId);
      if (entity != null && entity.Title != title)
        entity.Title = title;
      if (entity != null && entity.InitialStoryPoints != points)
        UpdatePoints(points, entity);
      return SaveChanges();
    }

    private void UpdatePoints(int points, BurnDownData entity)
    {
      var delta = points - entity.InitialStoryPoints;
      foreach (var point in entity.StoryPointsWrapList)
      {
        point.Value = point.Value + delta;
      }
      entity.InitialStoryPoints = points;
    }
  }
}
